/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.moderatorplugin;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.pearreview.ui.*;
import com.pearreview.ui.list.SeverityListCellRenderer;
import com.pearreview.application.Messages;
import com.pearreview.util.DoubleClickMouseAdapter;
import com.pearreview.util.review.Severity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class SeverityPanel extends PearPanel implements ModeratorPanel {
	private static final long serialVersionUID = -9109570500028164556L;
	private FormLabel severityLabel;
	private CompletableJTextField severityField;
	private JButton addBtn;
	private JScrollPane severityListScroll;
	private JList severityList;
	private JButton editBtn;
	private JButton deleteBtn;
	
	private JPanel container;
	private HeadingLabel heading;
	
	private FormLabel severityLabelEdit;
	private CompletableJTextField severityFieldEdit;
	private JButton addBtnEdit;
	private JButton abortBtnEdit;
	
	private JPanel newForm;
	private JPanel editForm;
	
	private DefaultListModel listModel;
	
	private NewSeverityAction newAction = new NewSeverityAction();
	private DeleteSeverityAction deleteAction = new DeleteSeverityAction();
	private EditSeverityAction editAction = new EditSeverityAction();
	
	private GroupLayout layout;
	private int editIndex;
	private int emptySeverityNum = 1;
	private boolean edit = false;
	private BottomButtonPanel bottom;
	
	public SeverityPanel() {
		initComponents();
	}

	private void initComponents() {
		setFont(new Font("Tahoma", Font.PLAIN, 12));
		
		severityLabel = new FormLabel();
		severityField = new CompletableJTextField();
		addBtn = new JButton();
		severityListScroll = new JScrollPane();
		severityList = new JList();
		editBtn = new JButton();
		deleteBtn = new JButton();
		
		severityLabelEdit = new FormLabel();
		severityFieldEdit = new CompletableJTextField();
		addBtnEdit = new JButton();
		abortBtnEdit = new JButton();

		//======== severityField ========
		severityField.addKeyListener(new AddKeyListener());
		severityFieldEdit.addKeyListener(new AddKeyListener());
		
		deleteAction.setEnabled(false);
		editAction.setEnabled(false);

		//---- severityLabel ----
		severityLabel.setText(
				getLocalizedString("severity"));
		
		//---- severityLabelEdit ----
		severityLabelEdit.setText(getLocalizedString("severity"));

		//---- addBtn ----
		addBtn.setAction(newAction);
		addBtn.setText(getLocalizedString("add"));
		addBtn.setFont(getFont());
		
		//---- addBtnEdit ----
		addBtnEdit.setAction(new EndEditSeverityAction());
		addBtnEdit.setText(getLocalizedString("save"));
		addBtnEdit.setFont(getFont());
		
		//---- abortBtnEdit ----
		abortBtnEdit.setAction(new AbortEditSeverityAction());
		abortBtnEdit.setText(getLocalizedString("abort_edit"));
		abortBtnEdit.setFont(getFont());

		//======== severityListScroll ========
		{
			severityListScroll.setViewportView(severityList);
			severityListScroll.setBorder(BorderFactory.createMatteBorder(
					1, 1, 1, 1, new Color(0x828790)));
			
			severityList.addListSelectionListener(new SeverityListListener());
			listModel = new DefaultListModel();
			severityList.setFont(getFont());
			SeverityListCellRenderer renderer = new SeverityListCellRenderer();
			severityList.addMouseListener(renderer);
			severityList.addMouseMotionListener(renderer);
			severityList.setCellRenderer(renderer);
			severityList.setModel(listModel);
			severityList.setSelectionBackground(new Color(0xbfd72b));
			severityList.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
			
			severityList.addMouseListener(new DoubleClickMouseAdapter() {
				private static final long serialVersionUID = 
						-8682497518051157504L;
				@Override
				public void mouseDoubleClicked(MouseEvent e) {
					editAction.actionPerformed(null);
				}
			});
		}

		//---- editBtn ----
		editBtn.setAction(editAction);
		editBtn.setText(getLocalizedString("edit"));
		editBtn.setFont(getFont());
		editBtn.setSelectedIcon(null);

		//---- deleteBtn ----
		deleteBtn.setAction(deleteAction);
		deleteBtn.setText(getLocalizedString("delete"));
		deleteBtn.setFont(getFont());
		
		container = new JPanel();
		container.setOpaque(false);
		
		newForm = new JPanel();
		newForm.setOpaque(false);
		
		GroupLayout newLayout = new GroupLayout(newForm);
		newForm.setLayout(newLayout);
		newLayout.setHorizontalGroup(newLayout.createSequentialGroup()
					.addComponent(severityLabel, 
							GroupLayout.PREFERRED_SIZE, 
							80, 
							80)
					.addGap(59, 59, 59)
					.addGroup(newLayout.createParallelGroup()
						.addComponent(addBtn)
							.addComponent(severityField, 
									GroupLayout.PREFERRED_SIZE, 
									300, 
									GroupLayout.PREFERRED_SIZE)));
		
		newLayout.setVerticalGroup(newLayout.createSequentialGroup()
							.addGroup(newLayout.createParallelGroup()
								.addComponent(severityField, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(severityLabel, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE))
							.addPreferredGap(
									LayoutStyle.ComponentPlacement.RELATED)
							.addComponent(addBtn));
		

		editForm = new JPanel();
		editForm.setOpaque(false);
		
		GroupLayout editLayout = new GroupLayout(editForm);
		editForm.setLayout(editLayout);
		editLayout.setHorizontalGroup(editLayout.createSequentialGroup()
					.addComponent(severityLabelEdit, 
							GroupLayout.PREFERRED_SIZE, 
							80, 
							80)
					.addGap(59, 59, 59)
					.addGroup(editLayout.createParallelGroup()
						.addGroup(editLayout.createParallelGroup()
								.addGroup(editLayout.createSequentialGroup()
								.addComponent(addBtnEdit)
								.addGap(10)
								.addComponent(abortBtnEdit)))
							.addComponent(severityFieldEdit, 
									GroupLayout.PREFERRED_SIZE, 
									300, 
									GroupLayout.PREFERRED_SIZE)));
		
		editLayout.setVerticalGroup(editLayout.createSequentialGroup()
							.addGroup(editLayout.createParallelGroup()
								.addComponent(severityFieldEdit, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE)
								.addComponent(severityLabelEdit, 
										GroupLayout.PREFERRED_SIZE, 
										GroupLayout.DEFAULT_SIZE, 
										GroupLayout.PREFERRED_SIZE))
							.addPreferredGap(
									LayoutStyle.ComponentPlacement.RELATED)
							.addGroup(editLayout.createParallelGroup()
									.addComponent(addBtnEdit)
									.addComponent(abortBtnEdit)));
		
		setForm(newForm);
		
		setLayout(new BorderLayout());
		add(container, BorderLayout.CENTER);
		
		heading = new HeadingLabel(
				Messages.getString("PearReview.Moderator.tabs.severities"));
		add(heading, BorderLayout.NORTH);
		
		bottom = new BottomButtonPanel();
		add(bottom, BorderLayout.SOUTH);
	}
	
	private void setForm(JPanel form) {
		container.removeAll();
		
		layout = new GroupLayout(container);
		container.setLayout(layout);
		layout.setHorizontalGroup(
				layout.createSequentialGroup()
				.addContainerGap()
						.addComponent(form)
							.addGap(30)
							.addGroup(layout.createParallelGroup()
								.addGroup(layout.createSequentialGroup()
									.addComponent(editBtn)
									.addPreferredGap(
											LayoutStyle
											.ComponentPlacement.RELATED)
									.addComponent(deleteBtn))
								.addComponent(severityListScroll, 
										GroupLayout.DEFAULT_SIZE, 
										217, 
										Short.MAX_VALUE))
					.addContainerGap()
		);
		
		layout.setVerticalGroup(
			layout.createParallelGroup()
				.addGroup(layout.createSequentialGroup()
					.addContainerGap()
					.addGroup(layout.createParallelGroup()
						.addComponent(severityListScroll, 
								GroupLayout.PREFERRED_SIZE, 
								GroupLayout.DEFAULT_SIZE, 
								GroupLayout.PREFERRED_SIZE)
						.addComponent(form)
					)
							
					.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
					.addGroup(layout.createParallelGroup()
						.addComponent(editBtn)
						.addComponent(deleteBtn))
					.addContainerGap(130, Short.MAX_VALUE))
		);
	}
	
	private static String getLocalizedString(String key) {
		return Messages.getString("PearReview.Moderator.severities." + key);
	}
	
	public void setSeverities(List<Severity> severities) {
		for (Severity severity: severities) {
			listModel.addElement(severity);
		}
	}
	
	public List<Severity> getSeverities() {
		List<Severity> severities = new ArrayList<Severity>();
		for (int i=0; i<listModel.size();i++) {
			severities.add((Severity)listModel.get(i));
		}
		return severities;
	}
	
	@Override
	public boolean isValidForm() {
		return !listModel.isEmpty();
	}
	
	private class SeverityListListener implements ListSelectionListener {
		@Override
		public void valueChanged(ListSelectionEvent e) {
			if(edit) {
				severityList.setSelectedIndex(editIndex);
				deleteAction.setEnabled(false);
				editAction.setEnabled(false);
			} else if (severityList.getSelectedIndices().length == 1) {
				deleteAction.setEnabled(true);
				editAction.setEnabled(true);
			} else if (severityList.getSelectedIndices().length > 1) {
				deleteAction.setEnabled(true);
				editAction.setEnabled(false);
			} else {
				deleteAction.setEnabled(false);
				editAction.setEnabled(false);
			}
		}
		
	}
	
	private class NewSeverityAction extends AbstractAction {
		private static final long serialVersionUID = 3411093256291038116L;
		@Override
		public void actionPerformed(ActionEvent e) {
			String severity;
			if (severityField.getText() == null 
					|| severityField.getText().equals("")) {
				severity = getLocalizedString("severity") + " " 
						+ emptySeverityNum;
				emptySeverityNum++;
			} else {
				severity = severityField.getText();
				severityField.addCompletion(severity);
				severityFieldEdit.addCompletion(severity);
			}
			severityField.setText(null);
			
			Object element = new Severity(severity);
			listModel.addElement(element);
			severityList.setSelectedValue(element, true);
		}
	}
	
	private class EditSeverityAction extends AbstractAction {
		private static final long serialVersionUID = -5545171107235460065L;
		@Override
		public void actionPerformed(ActionEvent e) {
			if(edit) {
				return;
			}
			int index = severityList.getSelectedIndex();
			if (index >= 0) {
				edit = true;
				Severity severity = (Severity)listModel.get(index);
				severityFieldEdit.setText(severity.getName());
				setForm(editForm);
				deleteAction.setEnabled(false);
				editAction.setEnabled(false);
				editIndex = index;
				heading.setCaption(
						Messages.getString(
								"PearReview.Moderator.tabs.severities") +
								" - " + getLocalizedString("edit_caption"), 
										true);
			}
		}
	}
	
	private class DeleteSeverityAction extends AbstractAction {

		private static final long serialVersionUID = -85748108958801790L;

		@Override
		public void actionPerformed(ActionEvent e) {
			Object[] severities = severityList.getSelectedValues();
			for(Object severity: severities) {
				listModel.removeElement(severity);
			}
		}
	}
	
	private class AbortEditSeverityAction extends AbstractAction {

		private static final long serialVersionUID = -2371861093414518034L;

		@Override
		public void actionPerformed(ActionEvent e) {
			edit = false;
			setForm(newForm);
			deleteAction.setEnabled(true);
			editAction.setEnabled(true);
			heading.setCaption(
					Messages.getString(
							"PearReview.Moderator.tabs.severities"), false);
		}
		
	}
	
	private class EndEditSeverityAction extends AbstractAction {

		private static final long serialVersionUID = -6647613393959930085L;

		@Override
		public void actionPerformed(ActionEvent e) {
			edit = false;
			Severity sev = (Severity)listModel.remove(editIndex);
			sev.setName(severityFieldEdit.getText());
			listModel.add(editIndex, sev);
			
			severityList.setSelectedValue(sev, false);
			
			severityField.addCompletion(severityFieldEdit.getText());
			severityFieldEdit.addCompletion(severityFieldEdit.getText());
			
			setForm(newForm);
			deleteAction.setEnabled(true);
			editAction.setEnabled(true);
			heading.setCaption(
					Messages.getString(
							"PearReview.Moderator.tabs.severities"), false);
		}
		
	}
	
	private class AddKeyListener implements KeyListener, Serializable {
		private static final long serialVersionUID = -1397017771787173267L;
		@Override
		public void keyPressed(KeyEvent e) {
			if(e.getKeyCode() == KeyEvent.VK_ENTER) {
				if(!edit)
					addBtn.doClick();
				else
					addBtnEdit.doClick();
			}			
		}
		@Override
		public void keyReleased(KeyEvent e) {
			// do nothing			
		}
		@Override
		public void keyTyped(KeyEvent e) {
			// do nothing			
		}		
	}

	@Override
	public String getHint() {
		return Messages.getString("PearReview.hint.moderator.severities");
	}

	@Override
	public String getErrorMessage() {
		return Messages.getString("PearReview.Moderator.tabs.severities_error");
	}

	@Override
	public void setNextViewAction(Action action) {
		bottom.setNextViewAction(action);
	}

	@Override
	public void setPreviousViewAction(Action action) {
		bottom.setPreviousViewAction(action);
	}
}
